Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(x/slashing): Avoid overslashing on redelegation + unbonding in specific situations #20688

Merged
merged 4 commits into from
Jun 24, 2024

Conversation

facundomedica
Copy link
Member

@facundomedica facundomedica commented Jun 17, 2024

Description

In some cases a user that performed a redelegation and a subsequent partial unbond would get slashed twice, once over its redelegation and once over its unbonding tokens.


Author Checklist

All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.

I have...

  • included the correct type prefix in the PR title, you can find examples of the prefixes below:
  • confirmed ! in the type prefix if API or client breaking change
  • targeted the correct branch (see PR Targeting)
  • provided a link to the relevant issue or specification
  • reviewed "Files changed" and left comments if necessary
  • included the necessary unit and integration tests
  • added a changelog entry to CHANGELOG.md
  • updated the relevant documentation or specification, including comments for documenting Go code
  • confirmed all CI checks have passed

Reviewers Checklist

All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.

Please see Pull Request Reviewer section in the contributing guide for more information on how to review a pull request.

I have...

  • confirmed the correct type prefix in the PR title
  • confirmed all author checklist items have been addressed
  • reviewed state machine logic, API design and naming, documentation is accurate, tests and test coverage

Summary by CodeRabbit

  • New Features

    • Updated SendCoinsFromModuleToModule method to separately accept senderModule and recipientModule.
    • Added TestOverSlashing to simulate and verify slashing scenarios in the blockchain network.
  • Bug Fixes

    • Corrected slashing logic to avoid overslashing unbonding delegations after redelegation.
  • Documentation

    • Updated CHANGELOG.md with details on bug fixes and new features.

Copy link
Contributor

coderabbitai bot commented Jun 17, 2024

Walkthrough

Walkthrough

The recent updates introduce significant changes to the MintBankKeeper interface, modify slashing logic in the staking module, and enhance testing for slashing scenarios. Specifically, the SendCoinsFromModuleToModule method now accepts separate parameters for sender and recipient modules. A new test function, TestOverSlashing, has been added to ensure correct behavior during slashing, redelegation, and undelegation operations. Additionally, the changelog for the staking module has been updated to document these adjustments and improvements.

Changes

File Change Summary
simapp/mint_fn.go Updated SendCoinsFromModuleToModule method in MintBankKeeper interface to accept separate sender and recipient module parameters.
tests/integration/slashing/keeper/slash_redelegation_test.go Added the TestOverSlashing function to simulate slashing scenarios, set up test accounts, and validate correct account balances.
x/staking/CHANGELOG.md Documented bug fix for avoiding overslashing unbonding delegations and feature update for MinCommissionRate handling.
x/staking/keeper/slash.go Modified SlashRedelegation method to alter the calculation logic for sharesToUnbond.

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@facundomedica facundomedica marked this pull request as ready for review June 17, 2024 13:39
@facundomedica facundomedica requested a review from a team as a code owner June 17, 2024 13:39
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review details

Configuration used: .coderabbit.yml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 9ab7d39 and 2216a3e.

Files selected for processing (4)
  • simapp/mint_fn.go (1 hunks)
  • tests/integration/slashing/keeper/slash_redelegation_test.go (1 hunks)
  • x/staking/CHANGELOG.md (1 hunks)
  • x/staking/keeper/slash.go (1 hunks)
Additional context used
Path-based instructions (4)
simapp/mint_fn.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/staking/CHANGELOG.md (1)

Pattern **/*.md: "Assess the documentation for misspellings, grammatical errors, missing documentation and correctness"

x/staking/keeper/slash.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

tests/integration/slashing/keeper/slash_redelegation_test.go (3)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.


Pattern tests/**/*: "Assess the integration and e2e test code assessing sufficient code coverage for the changes associated in the pull request"


Pattern **/*_test.go: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"

LanguageTool
x/staking/CHANGELOG.md

[style] ~99-~99: Consider a shorter alternative to avoid wordiness. (IN_ORDER_TO_PREMIUM)
Context: ...pi/cosmos/staking/v1beta1".Infraction_` in order to remove dependency between modules on st...


[misspelling] ~106-~106: Use “an” instead of ‘a’ if the following word starts with a vowel sound, e.g. ‘an article’, ‘an hour’. (EN_A_VS_AN)
Context: ...ub.com//pull/18841) In a undelegation or redelegation if the sha...

Markdownlint
x/staking/CHANGELOG.md

58-58: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


60-60: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


61-61: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


63-63: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


64-64: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


66-66: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


67-67: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


69-69: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


71-71: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


73-73: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


74-74: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


77-77: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


78-78: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


80-80: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


82-82: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


84-84: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


86-86: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


88-88: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


91-91: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


93-93: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


95-95: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


98-98: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


102-102: Expected: 2; Actual: 4 (MD007, ul-indent)
Unordered list indentation


50-50: Expected: 0 or 2; Actual: 1 (MD009, no-trailing-spaces)
Trailing spaces


101-101: Expected: 0 or 2; Actual: 1 (MD009, no-trailing-spaces)
Trailing spaces


44-44: null (MD024, no-duplicate-heading)
Multiple headings with the same content

Additional comments not posted (4)
simapp/mint_fn.go (1)

20-20: Refactored method signature to enhance clarity by separating sender and recipient module parameters.

Verification successful

The review comment regarding the refactored method signature SendCoinsFromModuleToModule in simapp/mint_fn.go has been verified. The search results indicate that the new method signature is used consistently across the codebase.

  • The new method signature is found in various files, including x/protocolpool/types/expected_keepers.go, x/mint/types/expected_keepers.go, x/gov/testutil/expected_keepers.go, and others.
  • The older signature with senderPool and recipientPool is still present in some mock files and tests (x/staking/testutil/expected_keepers_mocks.go), which might be intentional for backward compatibility in tests.

Please ensure that all instances, especially in test files, are updated to match the new signature if backward compatibility is not required.

Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify all function calls to `SendCoinsFromModuleToModule` match the new signature.

# Test: Search for the function usage. Expect: Only occurrences of the new signature.
rg --type go $'SendCoinsFromModuleToModule'

Length of output: 17735

x/staking/CHANGELOG.md (1)

30-30: The changelog entry correctly documents the bug fix for overslashing.

x/staking/keeper/slash.go (1)

Line range hint 368-392: Updated SlashRedelegation to handle moved delegations more accurately, preventing overslashing.

tests/integration/slashing/keeper/slash_redelegation_test.go (1)

189-392: Introduced TestOverSlashing to ensure that the new slashing logic does not result in overslashing. The test is well-structured and covers the necessary scenarios.

Copy link
Contributor

@alpe alpe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work! This fixes the issue as far as I can see. 💪
I added some comments and nits about the test. Feel free to ignore them

if err != nil {
return math.ZeroInt(), err
}
sharesToUnbond, err := dstVal.SharesFromTokensTruncated(slashAmount)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understood this correct, then you calculate the shares for the remaining slash amount. The slash amount may be (partially) filled from slashing unbonding delegations first. This looks correct to me and fixes the issue. Good work 👍


func TestOverSlashing(t *testing.T) {
// slash penalty percentage
slashFraction := "0.50"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: prefer an odd value so that you which half was actually used. Seeing some rounding can be interesting, too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed it to 45 👌


require.Equal(t, balance1AfterSlashing.Amount, balance2AfterSlashing.Amount)
require.Equal(t, balance2AfterSlashing.Amount, balance3AfterSlashing.Amount)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good test case.
There some more scenarios with multiple re-/undelegations that are not covered, yet. Maybe you can add them here, too.

For bonus points:

  • assert bondend and unbonded amounts separately to see how much of each was slashed
  • cover validator status unbonded
  • run into sharesToUnbond.GT(delegation.Shares)
  • (personal preference) refactor to a table test
// setup account and validators
	specs := map[string]struct {
		slashFrac math.LegacyDec
		del      []math.Int
		redel    []math.Int
		undel    []math.Int
		expBonded  math.Int
		expUnbonded  math.Int
	}{
		"": {},
	}
	for name, spec := range specs {
		t.Run(name, func(t *testing.T) {
// run with cacheContext ...
		})
	}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll take a look but I think I won't be able to make it a table test as afaict we need more than one delegation for this to happen

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Outside diff range and nitpick comments (1)
tests/integration/slashing/keeper/slash_redelegation_test.go (1)

81-91: Suggest using more descriptive validator details for clarity in tests.

The test validators are created with generic descriptions ("test"). Providing more descriptive or context-specific details might enhance the readability and maintainability of the test cases, especially when dealing with multiple validators.

Review details

Configuration used: .coderabbit.yml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 2216a3e and e503cb5.

Files selected for processing (1)
  • tests/integration/slashing/keeper/slash_redelegation_test.go (6 hunks)
Additional context used
Path-based instructions (1)
tests/integration/slashing/keeper/slash_redelegation_test.go (3)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.


Pattern tests/**/*: "Assess the integration and e2e test code assessing sufficient code coverage for the changes associated in the pull request"


Pattern **/*_test.go: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"

Additional comments not posted (3)
tests/integration/slashing/keeper/slash_redelegation_test.go (3)

76-77: Validation of account balances is correct.

The assertions correctly validate that the initial funding of accounts was successful by comparing the pre- and post-funding balances.


187-367: Comprehensive test for over-slashing scenarios is well-implemented.

The test function TestOverSlashing provides a detailed scenario to check for potential over-slashing issues. It includes multiple accounts and validators, and complex interactions like redelegations and undelegations. The logic appears sound, and the assertions are well-placed to validate the expected outcomes.


102-107: Check delegation logic for potential improvements.

The delegation logic is straightforward, but consider adding checks or logs to ensure that the delegation transactions are executed as expected, especially in complex test scenarios involving multiple actions.

Comment on lines +68 to +70
testCoin := sdk.NewCoin(bondDenom, stakingKeeper.TokensFromConsensusPower(ctx, 10))
fundAccount(t, ctx, bankKeeper, authKeeper, testAcc1, testCoin)
fundAccount(t, ctx, bankKeeper, authKeeper, testAcc2, testCoin)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure consistent funding logic across test cases.

The function fundAccount is used multiple times to set up initial conditions for the test accounts. Consider refactoring to a helper function that initializes multiple accounts to reduce redundancy and improve readability.

Comment on lines +123 to +133
redelMsg := stakingtypes.NewMsgBeginRedelegate(testAcc1.String(), evilValAddr.String(), goodValAddr.String(), testCoin)
_, err = stakingMsgServer.BeginRedelegate(ctx, redelMsg)
require.NoError(t, err)

// Acc 1 undelegate from good val
undelMsg := stakingtypes.NewMsgUndelegate(testAcc1.String(), goodValAddr.String(), testCoins[0])
undelMsg := stakingtypes.NewMsgUndelegate(testAcc1.String(), goodValAddr.String(), testCoin)
_, err = stakingMsgServer.Undelegate(ctx, undelMsg)
require.NoError(t, err)

// Acc 2 undelegate from evil val
undelMsg = stakingtypes.NewMsgUndelegate(testAcc2.String(), evilValAddr.String(), testCoins[0])
undelMsg = stakingtypes.NewMsgUndelegate(testAcc2.String(), evilValAddr.String(), testCoin)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip

Codebase Verification

Consider adding more detailed assertions post-redelegation and undelegation.

The current test file tests/integration/slashing/keeper/slash_redelegation_test.go contains assertions for errors but lacks specific checks on the state of delegations after redelegation and undelegation operations.

  • Add assertions to verify the state of delegations to ensure they reflect the expected changes accurately.
Analysis chain

Consider adding more detailed assertions post-redelegation and undelegation.

After performing redelegation and undelegation operations, it would be beneficial to add assertions checking the state of the delegations to ensure they reflect the expected changes accurately.

Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the state of delegations after redelegation and undelegation operations.
rg --type go 'GetDelegation' tests/integration/slashing/keeper

Length of output: 62



Script:

#!/bin/bash
# Description: Verify the presence of assertions or checks on the state of delegations after redelegation and undelegation operations.
# Search for assertion methods or patterns in the test file.
rg --type go 'require\..*' tests/integration/slashing/keeper/slash_redelegation_test.go

Length of output: 2151

@facundomedica facundomedica added this pull request to the merge queue Jun 24, 2024
Merged via the queue into main with commit 720c108 Jun 24, 2024
70 checks passed
@facundomedica facundomedica deleted the facu/fixoverslash branch June 24, 2024 10:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants